<?php
/* {
Citru - www.citru.se
See license.txt for copyright and license information.
} */

session_start();
define ("_CITRU", TRUE);
define ("_CITRU_REV", 99);
define ("_CITRU_RELEASE_NAME", "Alpha Yuzu");

class Citru {
	private $dbModule;
	private $userName;
	private $userGroups;
	
	private $templateName;
	private $pageName;
	
	private $citruVersion;
	private $citruReleaseName;
	
	
	/**
	 * Creates a Citru object. 
	 * A template-name can be specified.  
	 *
	 * @param string $template_name 	name of the template that runs this instance of Citru
	 * @param string $relative_path 	the relative path from the file that includes Citru to this file
	 * 
	 */
	function __construct($template_name="", $relative_path="") {
		define("ROOT", $relative_path);
		// Load Settings
		if(file_exists(ROOT.'config/settings.php')) {
			require ROOT.'config/settings.php';
		} else { die('settings.php not found. Run <a href="install.php">install.php</a> to install Citru.'); }
		if(file_exists(ROOT.'inc/CitruInstaller.php')) { die('Please remove inc/CitruInstaller.php before using Citru.'); }
		
		$this->templateName = $template_name;
		
		$page_name = $_GET['page'];
		if($page_name == '') { $page_name = 'default'; }
		if($this->checkPageName($page_name)) {
			$this->pageName = $page_name;
		}
		
		mb_internal_encoding("utf-8");
		mb_http_output("utf-8");
	}
	
	
// ___ Get functions ________________________
	
	/**
	 * Gives the content of a specified module/instance.
	 * If the logged in user has premissions, it gives an admin interface for the module instead.
	 *
	 * @param string $name			module type for the module that sould be returned
	 * @param string $instance		instance name for the module that should be returned
	 * @param boolean $dynamic		true if this module-instance changes when pageName does, false if it should remain the same
	 * 
	 */
	public function getModule($name, $instance, $dynamic=false) {
		$moduleName = $name.'Module';
		if($dynamic && $this->pageName != 'default') { $instance = $instance.'_'.$this->pageName; }
		$permissions = $this->hasPermissions($moduleName,$instance);
		$module = new $moduleName($instance, $this->dbModule, $permissions);
	
		if ($permissions['edit'] == true || $permissions['settings'] == true || $permissions['permissions'] == true):
			return $module->getAdminView();
		elseif ($permissions['view'] == true):
			return $module->getView();
		else:
			return '';
		endif;
	}
	
	/**
	 * Gives a navigation for administration at the top of the page
	 * 
	 * @return string 			html for the administration navigation
	 */
	public function getAdminNavigation() {
		$permissions = $this->hasPermissions('AdminNavModule','AdminNav');
		if($permissions['view'] == true ) {
			$nav .= '<div id="citru_admin_nav">'; 
			$nav .= $this->getModule('AdminNav', 'AdminNav', false);
			$nav .= '</div>';
		}
		return $nav;
	}
	
	
	/**
	 * Gives the title of the page, only works if the title is specified in the page panel
	 * 
	 * @return string 			the title of the page
	 */
	public function getTitle() {
		if($this->templateName != '') {
			$row = $this->getPageRow($this->templateName);
			$pages = split("\n",$row['page']);
			$titles = split("\n",$row['title']);
			
			foreach($pages as $i=>$p) {
				if($p == $this->pageName) {
					return $titles[$i];
				}
			}
			
		}
	}

// ___ Load functions _________________

	/**
	 * Loads a database module into $this->dbModule
	 * 
	 * @param string $db_type		database type. Also the name of the module ($db_type.'DbModule.php')
	 * @param string $db_host		host to connect to
	 * @param string $db_user		username to connect with
	 * @param string $db_pass		password to connect with
	 * @param string @db_name		name of database
	 * 
	 */
	private function loadDatabase($db_type='', $db_host='localhost', $db_user='', $db_pass='', $db_name='') {
		$dbModuleName = $db_type.'DbModule';
		
		try {
		require_once ROOT.'inc/db/'.$dbModuleName.'.php';
		$this->dbModule = new $dbModuleName($db_host, $db_user, $db_pass, $db_name);
		} catch(Exception $e) {
			echo $e->getMessage();
			die();
		}
	}
	
	/**
	 * Loads a module file for later use
	 * 
	 * @param string $name		name of the module
	 *
	 */
	private function loadModule($name) {
		require_once ROOT.'inc/modules/'.$name.'.php';
	}

	/**
	 * Loads an external library file for later use
	 * 
	 * @param string $name		name of the library
	 *
	 */	
	private function loadLib($name) {
		require_once ROOT.'inc/lib/'.$name.'.php';
	}


// ___ Templates and Pages ____________________

	private function checkPageName($page_name) {
		$pageRow = $this->getPageRow($this->templateName);
		foreach(split("\n", $pageRow['page']) as $page) {
			if(strcmp($page, $page_name) == 0) {
				return true;
			}
		}
		return false;
	}
	
	private function getPageRow($template_name) {
		$params = array( 	'table' => 'Pages',
		 					'condition' => 	array(
											array( 'template', '=', $template_name, '' )),
							'columns' => 'template, page, title' );
		$pageRow = $this->dbModule->findFirst($params);
		return $pageRow;
	}

// ___ Login __________________________

	/**
	 * Checks if a username/password combination is valid
	 * 
	 * @param string username		username to check
	 * @param string pass			password to check
	 * @return boolean				true if the combination is valid
	 */

	public function checkLogin($username, $pass) {
		$row = $this->getUserRow($username);
		if(strcmp(sha1(sha1($pass).$row['salt']), $row['hash']) == 0 ) {
			return true;
		}
		return false;
	}

// ___ Permissions ____________________
	
	/**
	 * Checks which permissions the logged in (or guest) user has for a specific instance of an module
	 * 
	 * @param string $name			name of the module
	 * @param string $instanve		name of the instance of the module
	 * @return boolean[]			a boolean hash with permissions for specific actions ex: array('view'=>true, 'edit'=>false)
	 * 
	 */
	private function hasPermissions($name, $instance) {
		// Get the user-id
		if(!isset($this->userId) || !isset($this->userGroups)) {
			$hash = $_SESSION['hash'];
			$user = $this->getUserRow();
        	
			// Compare the loginhash ($hash + salt) with the stored passwordhash ($user['hash']) for the user
			if( isset($user['id']) && strcmp(sha1($hash.$user['salt']), $user['hash']) == 0 ) {
				$this->userName = $user['name'];
				$this->userGroups = $user['groups'];
				$this->userGroups .= ',@all';
				
			} else {
				$this->userName = '';
				$this->userGroups = '@all';
			}
		}
		
		// Check if the user has permissions for the module-type
		$module_permissions = $this->checkPermissions($this->userName, $this->userGroups, $name, '');
		
		// Check if the user has permissions for the module-instance
		$instance_permissions = $this->checkPermissions($this->userName, $this->userGroups, $name, $instance);
		
		foreach ($module_permissions as $key => $val) {
			$permissions[$key] = $module_permissions[$key] | $instance_permissions[$key];
		}
		
		// Return any granted permissions
		return $permissions;
	}
	
	/**
	 * Checks which permissions a user/group has for a specific module-instance
	 * 
	 * @param string $user			name of the user to check permissions for
	 * @param string $user_group	groups the user belongs to, comma separated
	 * @param string $name			name of the module to check permissions for
	 * @param string $instance		name of the instance of the module
	 * @return boolean[]			a boolean hash with permissions for specific actions ex: array('view'=>true, 'edit'=>false)
	 * 
	 */
	private function checkPermissions($user, $user_groups, $name, $instance) {
		// Get permissions for the module
		$params = array( 	'table' => 'Permissions',
		 					'condition' => 	array(
											array( 'module','=', $name, 'AND' ), 
											array( 'instance', '=', $instance, '' ) ),
							'columns' => 'permissions' );
		$db_permissions = $this->dbModule->findFirst($params);
		if(!$db_permissions) { return array(); }
		
		$permissions_rows = split("\n", $db_permissions['permissions']);
		foreach($permissions_rows as $row) {
			$tmp = split("=", $row);
			$key = trim($tmp[0]);
			$val = trim($tmp[1]);
			$permissions[$key]  = $this->comparePermissions($val, $user);
			$permissions[$key] |= $this->comparePermissions($val, $user_groups);
		}
		
		return $permissions;
	}
	
	/**
	 * Returns a array of id, hash, salt and groups for the active user
	 * 
	 * @return string[]			a string array with id, hash, salt and groups for a user
	 * 
	 */
	private function getUserRow($user='') {
		if($user != '') { $user_name = $user; }
		else { $user_name = $_SESSION['user']; }
		$params = array( 	'table' => 'Users',
		 					'condition' => 	array(
											array( 'name', '=', $user_name, '' ) ),
							'columns' => 'id, hash, salt, groups' );
		$user = $this->dbModule->findFirst($params);
		return $user;
	}

	/**
	 * Compares allowed users/groups to specified user/groups
	 * 
	 * @param string $allowed	users/groups that's allowed permission, comma separated
	 * @param string $id		users/groups to compare with, comma separated
	 * @return boolean			true if permissions is granted			
	 * 
	 */
	// Compare permissions: Used by checkPermissions to compare allowed users/groups with specified user/groups
	private function comparePermissions($allowed, $id) {
		if($allowed == '') { return false; }
		
		$id = split(',', $id);
		$allowed = split(',', $allowed);
		
		foreach( $allowed as $a ) {
			foreach( $id as $i ) {
				if($a === $i) { return true; }
			}
		}

		return false;
	}
	
}

?>
